package com.bruce.exec.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期参数替换,基于${SCHEDULE_DATE}进行日期计算并支持日期加减操作,输出为标准日期格式：yyyy-MM-dd
 * <p>
 * 例：
 * ${SCHEDULE_DATE} 表示当天日期
 * ${SCHEDULE_DATE-1} 表示当天日期前一天
 * ${SCHEDULE_DATE+1} 表示当天日期后一天
 *
 * @author xin.ding
 * @date 2021/6/1 8:45
 */

public class DateParameter {

    /** 基础日期变量名称 */
    private static final String BASE_DATE_NAME = "SCHEDULE_DATE";

    /** 日期计算加操作 */
    private static final String ADD = "+";
    /** 日期计算减操作 */
    private static final String SUB = "-";

    /** 日期变量前缀 */
    private static final String PARAM_BEGIN = "${";
    /** 日期 变量后缀 */
    private static final String PARAM_END = "}";

    /** 参数表达式非贪婪匹配(.*?匹配最小) */
    private static final Pattern EXPRESSION_PATTERN = Pattern.compile(CharSequenceUtil.format(".*?\\$\\{(?<exp>\\s*{}\\s*([\\+\\-]{1}\\s*\\d\\s*)?)\\}.*", BASE_DATE_NAME), Pattern.CASE_INSENSITIVE);

    /**
     *
     */
    private DateParameter() {
        throw new UnsupportedOperationException();
    }

    /**
     * 日期参数替换 yyyy-MM-DD
     *
     * @param parameter 参数
     * @param schDate   替换日期
     * @return
     */
    public static String refactor(String parameter, String schDate) {
        return refactor(parameter, schDate, DatePattern.NORM_DATE_PATTERN);
    }

    /**
     * 日期参数替换
     *
     * @param parameter  参数
     * @param schDate    替换日期
     * @param outPattern 日期输出格式
     * @return
     */
    public static String refactor(String parameter, String schDate, String outPattern) {
        final Matcher matcher = EXPRESSION_PATTERN.matcher(parameter);
        String expression;
        if (matcher.find()) {
            try {
                expression = matcher.group("exp");
                if (CharSequenceUtil.isEmpty(expression)) {
                    throw new IllegalArgumentException("日期表达式格式错误!");
                }
                expression = expression.trim().toUpperCase();
                if (!expression.startsWith(BASE_DATE_NAME)) {
                    throw new IllegalArgumentException("日期表达式必须包含" + BASE_DATE_NAME);
                }

                final DateTime baseDate = DateUtil.parse(schDate, DatePattern.PURE_DATE_PATTERN, DatePattern.NORM_DATE_PATTERN);

                int offset;
                if (expression.equals(BASE_DATE_NAME)) {
                    offset = 0;
                } else if (expression.contains(ADD)) {
                    offset = NumberUtil.parseInt(expression.substring(expression.indexOf(ADD) + ADD.length()).trim());
                } else if (expression.contains(SUB)) {
                    offset = NumberUtil.parseInt(expression.substring(expression.indexOf(SUB) + SUB.length()).trim()) * -1;
                } else {
                    throw new IllegalArgumentException("日期表达式" + expression + "不支持!");
                }

                final DateTime dateTime = DateUtil.offsetDay(baseDate, offset);
                final String dateTimeStr = DateUtil.format(dateTime, outPattern);

                final int begin = parameter.indexOf(PARAM_BEGIN);
                final int end = parameter.indexOf(PARAM_END, begin);
                final String substring = parameter.substring(begin, end + PARAM_END.length());
                final String ret = parameter.replace(substring, dateTimeStr);
                if (EXPRESSION_PATTERN.matcher(ret).find()) {
                    return refactor(ret, schDate, outPattern);
                } else {
                    return ret;
                }
            } catch (Exception e) {
                throw new RuntimeException("日期参数替换失败:" + e.getMessage());
            }
        }
        return parameter;
    }
}
